package com.yu.mail.starter.service;

import com.yu.mail.starter.configs.MailSender;
import com.yu.mail.starter.exceptions.MailException;
import com.yu.mail.starter.utils.ThreadUtil;
import com.yu.mail.starter.properties.MailProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.StringUtils;

import javax.mail.internet.MimeMessage;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 邮件服务类
 * @author yuhh
 * @date 2021-05-24 17:24
 **/
public class MailService {

    /** logger */
    private static final Logger logger = LoggerFactory.getLogger(MailService.class);

    /** 邮件线程名 */
    private static final String MAIL_THREAD_NAME = "mailThread";

    /** 邮件线程池 */
    private static final ThreadPoolExecutor SEND_MAIL_EXECUTOR = ThreadUtil.buildThreadPool(MAIL_THREAD_NAME);

    private MailProperties mailProperties;

    private JavaMailSenderImpl mailSender;

    /**
     * 发送邮件--以html格式
     * @param to 接受人，多个以","分割
     * @param subject 主题
     * @param html 发送内容(html代码)
     * @author yuhh
     * @date 2019/11/27 16:37
     */
    public void sendMailForHtml(String to, String subject, String html) {
        sendMailForHtmlHaveAttachment(to, subject, html, null, null);
    }

    /**
     * 发送邮件--以html格式
     * @param subject 主题
     * @param html 发送内容(html代码)
     * @author yuhh
     * @date 2019/11/27 16:37
     */
    public void sendMailForHtml(String subject, String html) {
        sendMailForHtmlHaveAttachment(mailProperties.getSendEmail(), subject, html, null, null);
    }

    /**
     * 发送邮件--普通文本
     * @param to 接受人，多个以","分割
     * @param subject 主题
     * @param text 发送内容
     * @author yuhh
     * @date 2019/11/27 16:37
     */
    public void sendMailBasic(String to, String subject, String text) {
        sendMail(to, subject, text, false, null, null);
    }

    /**
     * 发送邮件--普通文本
     * @param subject 主题
     * @param text 发送内容
     * @author yuhh
     * @date 2019/11/27 16:37
     */
    public void sendMailBasic(String subject, String text) {
        sendMail(mailProperties.getSendEmail(), subject, text, false, null, null);
    }

    /**
     * 发送邮件--以html格式，带附件
     * @param to 接受人，多个以","分割
     * @param subject 主题
     * @param html 发送内容(html代码)
     * @param suffixName 附件后缀名
     * @param inputStreamSource 文件inputStreamSource
     * @author yuhh
     * @date 2019/11/27 16:37
     */
    public void sendMailForHtmlHaveAttachment(String to, String subject, String html, String suffixName, InputStreamSource inputStreamSource) {
        sendMail(to, subject, html, true, suffixName, inputStreamSource);
    }

    /**
     * 发送邮件--以html格式，带附件
     * @param subject 主题
     * @param html 发送内容(html代码)
     * @param suffixName 附件后缀名
     * @param inputStreamSource 文件inputStreamSource
     * @author yuhh
     * @date 2019/11/27 16:37
     */
    public void sendMailForHtmlHaveAttachment(String subject, String html, String suffixName, InputStreamSource inputStreamSource) {
        sendMail(mailProperties.getSendEmail(), subject, html, true, suffixName, inputStreamSource);
    }

    /**
     * 发送邮件
     * @param to 接受人，多个以","分割
     * @param subject 主题
     * @param test 发送内容
     * @param isHtml 发送内容是否是html代码
     * @param suffixName 附件后缀名
     * @param inputStreamSource 文件inputStreamSource
     * @author yuhh
     * @date 2019/11/27 16:37
     */
    private void sendMail(String to, String subject, String test,  boolean isHtml,
                                 String suffixName, InputStreamSource inputStreamSource){
        if (!mailProperties.getSend()){
            logger.info("配置无需发送邮件");
            return;
        }
        if (StringUtils.isEmpty(to)){
            throw new MailException("收件人为空");
        }
        if (StringUtils.isEmpty(subject)){
            throw new MailException("邮件主题为空");
        }
        if (StringUtils.isEmpty(test)){
            throw new MailException("邮件内容为空");
        }
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper messageHelper = getMessageHelper(mimeMessage, subject, test, isHtml, suffixName, inputStreamSource);
        SEND_MAIL_EXECUTOR.execute(new SendMailThread(messageHelper, mimeMessage, to));
    }

    /**
     * 获取邮件内容
     * @param mimeMessage 邮件发送器信息
     * @param subject 主题
     * @param test 发送内容
     * @param isHtml 发送内容是否是html代码
     * @param suffixName 附件后缀名
     * @param inputStreamSource 文件inputStreamSource
     * @return org.springframework.mail.javamail.MimeMessageHelper
     * @author yuhh
     * @date 2019/11/28 14:38
     */
    private MimeMessageHelper getMessageHelper(MimeMessage mimeMessage, String subject, String test, boolean isHtml,
                                                      String suffixName, InputStreamSource inputStreamSource) {
        try {
            // 设置utf-8或GBK编码，否则邮件会有乱码
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            messageHelper.setFrom(mailProperties.getMailEmailFrom(), mailProperties.getMailPersonal());
            messageHelper.setSubject(subject);
            messageHelper.setText(test, isHtml);
            if (inputStreamSource != null) {
                messageHelper.addAttachment(subject + suffixName, inputStreamSource);
            }
            return messageHelper;
        } catch (Exception e) {
            logger.error("构建邮件内容出现异常", e);
        }
        return null;
    }

    /**
     * 发送邮件线程类
     * @author yuhh
     * @date 2019/11/28 15:34
     */
    private class SendMailThread implements Runnable{

        /** 邮件内容 */
        private final MimeMessageHelper messageHelper;
        /** 邮件发送器 */
        private final MimeMessage mimeMessage;
        /** 接受人，多个以","分割 */
        private final String to;

        private SendMailThread(MimeMessageHelper messageHelper, MimeMessage mimeMessage, String to){
            this.messageHelper = messageHelper;
            this.mimeMessage = mimeMessage;
            this.to = to;
        }

        @Override
        public void run() {
            try{
                messageHelper.setTo(to.split(","));
                mailSender.send(mimeMessage);
            } catch (Exception e) {
                logger.error("发送给‘{}’的邮件异常", to, e);
            }
        }
    }

    public MailService(MailProperties mailProperties, MailSender mailSender){
        this.mailProperties = mailProperties;
        this.mailSender = mailSender.createMailSender();
    }

    public MailService(){}
}
